//@version=5
indicator("FREE ALGOs [AI Signals Gold]", overlay=true, precision=0, explicit_plot_zorder=true, max_labels_count=500)
 
//------------------ AI Signals | https://www.getaisignals.com ---------------//
// Get user input
sensitivity = input.float(4, "  Sensitivity (0.5 - 5)", 0.5, 5, step=0.1)
emaCloud    = input.bool(false, "EMA Cloud")
suppRes     = input.bool(false, "Support & Resistance")
breaks      = input.bool(false, "Breaks")
usePsar     = input.bool(false, "PSAR")
emaEnergy   = input.bool(false, "EMA Energy")

Ema200       = input.bool(true, "EMA 200")
plot(Ema200 ? ta.ema(close, 200) : na, title="EMA 200", editable=true )


// Functions
supertrend(_src, factor, atrLen) =>
	atr = ta.atr(atrLen)
	upperBand = _src + factor * atr
	lowerBand = _src - factor * atr
	prevLowerBand = nz(lowerBand[1])
	prevUpperBand = nz(upperBand[1])
	lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
	upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
	int direction = na
	float superTrend = na
	prevSuperTrend = superTrend[1]
	if na(atr[1])
		direction := 1
	else if prevSuperTrend == prevUpperBand
		direction := close > upperBand ? -1 : 1
	else
		direction := close < lowerBand ? 1 : -1
	superTrend := direction == -1 ? lowerBand : upperBand
	[superTrend, direction]
// Get Components
ocAvg       = math.avg(open, close)
ema1        = ta.ema(high, 9)
ema2        = ta.ema(high, 12)
ema3        = ta.ema(high, 15)
ema4        = ta.ema(high, 18)
sma1        = ta.sma(close, 5)
sma2        = ta.sma(close, 6)
sma3        = ta.sma(close, 7)
sma4        = ta.sma(close, 8)
sma5        = ta.sma(close, 9)
sma6        = ta.sma(close, 10)
sma7        = ta.sma(close, 11)
sma8        = ta.sma(close, 12)
sma9        = ta.sma(close, 13)
sma10       = ta.sma(close, 14)
sma11       = ta.sma(close, 15)
sma12       = ta.sma(close, 16)
sma13       = ta.sma(close, 17)
sma14       = ta.sma(close, 18)
sma15       = ta.sma(close, 19)
sma16       = ta.sma(close, 20)
psar        = ta.sar(0.02, 0.02, 0.2)
[supertrend, direction] = supertrend(close, sensitivity, 11)
barsL       = 10
barsR       = 10
pivotHigh = fixnan(ta.pivothigh(barsL, barsR)[1])
pivotLow = fixnan(ta.pivotlow(barsL, barsR)[1])
// Colors
green       = #2BBC4D, green2   = #00DD00
red         = #C51D0B, red2     = #DD0000
emaCloudColor = emaCloud ? (close > supertrend ? #71CD6D : #D75131) : na
emaEnergyColor(ma) => emaEnergy ? (close >= ma ? green : red) : na
// Plots
p1 = plot(ema1, "", na, editable=false)
p2 = plot(ema2, "", emaCloudColor, editable=false)
p3 = plot(ema3, "", emaCloudColor, editable=false)
p4 = plot(ema4, "", na, editable=false)
fill(p1, p2, emaCloud ? (ema2 > ema3 ? color.new(#D75131, 80) : color.new(#71CD6D, 80)) : na)
fill(p4, p3, emaCloud ? (ema2 < ema3 ? color.new(#D75131, 80) : color.new(#71CD6D, 80)) : na)
fill(p2, p3, emaCloud ? color.new(emaCloudColor, 35) : na)
plot(sma1, "", emaEnergyColor(sma1), editable=false)
plot(sma2, "", emaEnergyColor(sma2), editable=false)
plot(sma3, "", emaEnergyColor(sma3), editable=false)
plot(sma4, "", emaEnergyColor(sma4), editable=false)
plot(sma5, "", emaEnergyColor(sma5), editable=false)
plot(sma6, "", emaEnergyColor(sma6), editable=false)
plot(sma7, "", emaEnergyColor(sma7), editable=false)
plot(sma8, "", emaEnergyColor(sma8), editable=false)
plot(sma9, "", emaEnergyColor(sma9), editable=false)
plot(sma10, "", emaEnergyColor(sma10), editable=false)
plot(sma11, "", emaEnergyColor(sma11), editable=false)
plot(sma12, "", emaEnergyColor(sma12), editable=false)
plot(sma13, "", emaEnergyColor(sma13), editable=false)
plot(sma14, "", emaEnergyColor(sma14), editable=false)
plot(sma15, "", emaEnergyColor(sma15), editable=false)
plot(sma16, "", emaEnergyColor(sma16), editable=false)
barcolor(close > supertrend ? #2BE300 : red2)


autoTL      = input.bool(false, "Auto Trend Lines")

lr_slope(_src, _len) =>
    x = 0.0, y = 0.0, x2 = 0.0, xy = 0.0
    for i = 0 to _len - 1
        val = _src[i]
        per = i + 1
        x += per
        y += val
        x2 += per * per
        xy += val * per
    _slp = (_len * xy - x * y) / (_len * x2 - x * x)
    _avg = y / _len
    _int = _avg - _slp * x / _len + _slp
    [_slp, _avg, _int]
lr_dev(_src, _len, _slp, _avg, _int) =>
    upDev = 0.0, dnDev = 0.0
    val = _int
    for j = 0 to _len - 1
        price = high[j] - val
        if price > upDev
            upDev := price
        price := val - low[j]
        if price > dnDev
            dnDev := price
        price := _src[j]
        val += _slp
    [upDev, dnDev]

source = close, period = 150
[s, a, i] = lr_slope(source, period)
[upDev, dnDev] = lr_dev(source, period, s, a, i)



x1 = bar_index - period + 1, _y1 = i + s * (period - 1), x2 = bar_index, _y2 = i
upperTL = autoTL ? line.new(x1, _y1 + upDev, x2, _y2 + upDev, xloc.bar_index, extend.none, red) : na
line.delete(upperTL[1])
middleTL = autoTL ? line.new(x1, _y1, x2, _y2, xloc.bar_index, extend.none, color.white) : na
line.delete(middleTL[1])
lowerTL = autoTL ? line.new(x1, _y1 - dnDev, x2, _y2 - dnDev, xloc.bar_index, extend.none, green) : na
line.delete(lowerTL[1])

p5 = plot(ocAvg, "", na, editable=false)
p6 = plot(psar, "PSAR", usePsar ? (psar < ocAvg ? green : red) : na, 1, plot.style_circles, editable=false)
fill(p5, p6, usePsar ? (psar < ocAvg ? color.new(green, 90) : color.new(red, 90)) : na, editable=false)
y1 = low - (ta.atr(30) * 2)
y2 = high + (ta.atr(30) * 2)
bull = ta.crossover(close, supertrend) and close >= sma9
bear = ta.crossunder(close, supertrend) and close <= sma9
buy  = bull ? label.new(bar_index, y1, "BUY", xloc.bar_index, yloc.price, #2BE300, label.style_label_up, color.white, size.normal) : na
sell = bear ? label.new(bar_index, y2, "SELL", xloc.bar_index, yloc.price, red2, label.style_label_down, color.white, size.normal) : na
plot(pivotHigh, "Resistance", not suppRes or ta.change(pivotHigh) ? na : red, 2, offset=-(barsR + 1), editable=false)
plot(pivotLow, "Support", not suppRes or ta.change(pivotLow) ? na : green, 2, offset=-(barsR + 1), editable=false)
plotshape(breaks and ta.crossover(close, pivotHigh), "Break", shape.labelup, location.belowbar, green, 0, "B", color.white, false, size.small)
plotshape(breaks and ta.crossunder(close, pivotLow), "Break", shape.labeldown, location.abovebar, red, 0, "B", color.white, false, size.small)

levels      = input.bool(true, "Show TP & SL", group="TP & SL")
lvlLines    = (true)
linesStyle  = ("SOLID")
lvlDecimals = (4)
lvlDistance = (1)
atrLen      = (14)
atrRisk     = input.int(defval=4, minval=1, maxval=4, title="Risk To Reward", group="TP & SL")

decimals  = lvlDecimals == 1 ? "#.#" : lvlDecimals == 2 ? "#.##" : lvlDecimals == 3 ? "#.###" : lvlDecimals == 4 ? "#.####" : lvlDecimals == 5 ? "#.#####" : lvlDecimals == 6 ? "#.######" : lvlDecimals == 7 ? "#.#######" : "#.########"
trigger = bull ? 1 : 0
trigger2 = bear ? 0 : 1
atrBand = ta.atr(atrLen) * atrRisk
atrStop = trigger == 1 ? low - atrBand : high + atrBand
atrStop2 = trigger2 == -1 ? high + atrBand : low - atrBand

countBull = ta.barssince(bull)
countBear = ta.barssince(bear)

lastTrade(src) => ta.valuewhen((bull) or (bear), src, 0)
entry = levels ? label.new(time, close, "Entry: " + str.tostring(lastTrade(close), decimals), xloc.bar_time, yloc.price, color.rgb(4,218,253,0), label.style_label_left, color.black, size.small) : na
label.set_x(entry, label.get_x(entry) + math.round(ta.change(time) * lvlDistance))
label.set_y(entry, lastTrade(close))
label.delete(entry[1])
stop_y = lastTrade(atrStop)
stop  = levels ? label.new(time, close, "Stop Loss: " + str.tostring(stop_y, decimals), xloc.bar_time, yloc.price, color.rgb(255,82,83,0), label.style_label_left, color.black, size.small) : na
label.set_x(stop, label.get_x(stop) + math.round(ta.change(time) * lvlDistance))
label.set_y(stop, stop_y)
label.delete(stop[1])
tp1_y = (lastTrade(close)-lastTrade(atrStop))*1 + lastTrade(close)
tp1   = levels ? label.new(time, close, "Take Profit 1: " + str.tostring(tp1_y, decimals), xloc.bar_time, yloc.price, color.rgb(77,174,81,0), label.style_label_left, color.black, size.small) : na
label.set_x(tp1, label.get_x(tp1) + math.round(ta.change(time) * lvlDistance))
label.set_y(tp1, tp1_y)
label.delete(tp1[1])
tp15_y = (lastTrade(close)-lastTrade(atrStop))*1.5 + lastTrade(close)
tp15   = levels ? label.new(time, close, "Take Profit 2: " + str.tostring(tp15_y, decimals), xloc.bar_time, yloc.price, color.rgb(77,174,81,0), label.style_label_left, color.black, size.small) : na
label.set_x(tp15, label.get_x(tp15) + math.round(ta.change(time) * lvlDistance))
label.set_y(tp15, tp15_y)
label.delete(tp15[1])
tp2_y = (lastTrade(close)-lastTrade(atrStop))*2 + lastTrade(close)
tp2   = levels ? label.new(time, close, "Take Profit 3: " + str.tostring(tp2_y, decimals), xloc.bar_time, yloc.price, color.rgb(77,174,81,0), label.style_label_left, color.black, size.small) : na
label.set_x(tp2, label.get_x(tp2) + math.round(ta.change(time) * lvlDistance))
label.set_y(tp2, tp2_y)
label.delete(tp2[1])
tp3_y = (lastTrade(close)-lastTrade(atrStop))*3 + lastTrade(close)
tp3   = levels ? label.new(time, close, "Take Profit 4: " + str.tostring(tp3_y, decimals), xloc.bar_time, yloc.price, color.rgb(77,174,81,0), label.style_label_left, color.black, size.small) : na
label.set_x(tp3, label.get_x(tp3) + math.round(ta.change(time) * lvlDistance))
label.set_y(tp3, tp3_y)
label.delete(tp3[1])

style = linesStyle == "SOLID" ? line.style_solid : linesStyle == "DASHED" ? line.style_dashed : line.style_dotted
lineEntry = levels and lvlLines ? line.new(bar_index - (trigger == 0 ? countBull : countBear), lastTrade(close), bar_index + lvlDistance, lastTrade(close), xloc.bar_index, extend.none, color.rgb(0,217,252), style, 2) : na, line.delete(lineEntry[1])
lineStop  = levels and lvlLines ? line.new(bar_index - (trigger == 0 ? countBull : countBear), stop_y, bar_index + lvlDistance, stop_y, xloc.bar_index, extend.none, color.red, style, 2) : na, line.delete(lineStop[1])
lineTp1   = levels and lvlLines ? line.new(bar_index - (trigger == 0 ? countBull : countBear), tp1_y, bar_index + lvlDistance, tp1_y, xloc.bar_index, extend.none, color.green, style, 2) : na, line.delete(lineTp1[1])
lineTp15  = levels and lvlLines ? line.new(bar_index - (trigger == 0 ? countBull : countBear), tp15_y, bar_index + lvlDistance, tp15_y, xloc.bar_index, extend.none, color.green, style, 2) : na, line.delete(lineTp15[1])
lineTp2   = levels and lvlLines ? line.new(bar_index - (trigger == 0 ? countBull : countBear), tp2_y, bar_index + lvlDistance, tp2_y, xloc.bar_index, extend.none, color.green, style, 2) : na, line.delete(lineTp2[1])
lineTp3   = levels and lvlLines ? line.new(bar_index - (trigger == 0 ? countBull : countBear), tp3_y, bar_index + lvlDistance, tp3_y, xloc.bar_index, extend.none, color.green, style, 2) : na, line.delete(lineTp3[1])

// Alerts
alertcondition(bull or bear, "AI Signal Alert", "AI Signals Gold\nAlert Triggered on {{ticker}} @ {{close}}")
alertcondition(bull, "Alert Buy", "AI Signals Gold\nBuy {{ticker}} @ {{close}}")
alertcondition(bear, "Alert Sell", "AI Signals Gold\nSell {{ticker}} @ {{close}}")
alertcondition(ta.crossover(close, pivotHigh), "Broke Resistance", "AI Signals Gold\nBroke Resistance on {{ticker}} @ {{close}}")
alertcondition(ta.crossunder(close, pivotLow), "Broke Support", "AI Signals Gold\nBroke Support on {{ticker}} @ {{close}}")

prd = (10)
ppsrc = ('High/Low')
maxnumpp = (20)
ChannelW = (10)
maxnumsr = (5)
min_strength = (2)
labelloc = (0)
linestyle = input.string(defval='Dashed', title='Line Style', options=['Solid', 'Dotted', 'Dashed'], group="S & R")
linewidth = input.int(defval=2, title='Line Width', minval=1, maxval=4, group="S & R")
resistancecolor = (color.rgb(255,0,146,0))
supportcolor = (color.rgb(0,186,255,0))
showpp = (false)

float src1 = ppsrc == 'High/Low' ? high : math.max(close, open)
float src2 = ppsrc == 'High/Low' ? low : math.min(close, open)
float ph = ta.pivothigh(src1, prd, prd)
float pl = ta.pivotlow(src2, prd, prd)


Lstyle = linestyle == 'Dashed' ? line.style_dashed : linestyle == 'Solid' ? line.style_solid : line.style_dotted

//calculate maximum S/R channel zone width
prdhighest = ta.highest(300)
prdlowest = ta.lowest(300)
cwidth = (prdhighest - prdlowest) * ChannelW / 100

var pivotvals = array.new_float(0)

if ph or pl
    array.unshift(pivotvals, ph ? ph : pl)
    if array.size(pivotvals) > maxnumpp  // limit the array size
        array.pop(pivotvals)

get_sr_vals(ind) =>
    float lo = array.get(pivotvals, ind)
    float hi = lo
    int numpp = 0
    for y = 0 to array.size(pivotvals) - 1 by 1
        float cpp = array.get(pivotvals, y)
        float wdth = cpp <= lo ? hi - cpp : cpp - lo
        if wdth <= cwidth  // fits the max channel width?
            lo := cpp <= lo ? cpp : lo
            hi := cpp > lo ? cpp : hi
            numpp += 1
            numpp
    [hi, lo, numpp]

var sr_up_level = array.new_float(0)
var sr_dn_level = array.new_float(0)
sr_strength = array.new_float(0)

find_loc(strength) =>
    ret = array.size(sr_strength)
    for i = ret > 0 ? array.size(sr_strength) - 1 : na to 0 by 1
        if strength <= array.get(sr_strength, i)
            break
        ret := i
        ret
    ret

check_sr(hi, lo, strength) =>
    ret = true
    for i = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        //included?
        if array.get(sr_up_level, i) >= lo and array.get(sr_up_level, i) <= hi or array.get(sr_dn_level, i) >= lo and array.get(sr_dn_level, i) <= hi
            if strength >= array.get(sr_strength, i)
                array.remove(sr_strength, i)
                array.remove(sr_up_level, i)
                array.remove(sr_dn_level, i)
                ret
            else
                ret := false
                ret
            break
    ret

var sr_lines = array.new_line(11, na)
var sr_labels = array.new_label(11, na)

for x = 1 to 10 by 1
    rate = 100 * (label.get_y(array.get(sr_labels, x)) - close) / close
    label.set_text(array.get(sr_labels, x), text=str.tostring(label.get_y(array.get(sr_labels, x))) + '(' + str.tostring(rate, '#.##') + '%)')
    label.set_x(array.get(sr_labels, x), x=bar_index + labelloc)
    label.set_color(array.get(sr_labels, x), color=label.get_y(array.get(sr_labels, x)) >= close ? color.rgb(0,186,255,100) : color.rgb(255,0,146,100))
    label.set_textcolor(array.get(sr_labels, x), textcolor=label.get_y(array.get(sr_labels, x)) >= close ? color.rgb(0,186,255,100) : color.rgb(0,186,255,100))
    line.set_color(array.get(sr_lines, x), color=line.get_y1(array.get(sr_lines, x)) >= close ? resistancecolor : supportcolor)

if ph or pl
    //because of new calculation, remove old S/R levels
    array.clear(sr_up_level)
    array.clear(sr_dn_level)
    array.clear(sr_strength)
    //find S/R zones
    for x = 0 to array.size(pivotvals) - 1 by 1
        [hi, lo, strength] = get_sr_vals(x)
        if check_sr(hi, lo, strength)
            loc = find_loc(strength)
            // if strength is in first maxnumsr sr then insert it to the arrays 
            if loc < maxnumsr and strength >= min_strength
                array.insert(sr_strength, loc, strength)
                array.insert(sr_up_level, loc, hi)
                array.insert(sr_dn_level, loc, lo)
                // keep size of the arrays = 5
                if array.size(sr_strength) > maxnumsr
                    array.pop(sr_strength)
                    array.pop(sr_up_level)
                    array.pop(sr_dn_level)

    for x = 1 to 10 by 1
        line.delete(array.get(sr_lines, x))
        label.delete(array.get(sr_labels, x))

    for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
        rate = 100 * (mid - close) / close
        array.set(sr_labels, x + 1, label.new(x=bar_index + labelloc, y=mid, text=str.tostring(mid) + '(' + str.tostring(rate, '#.##') + '%)', color=mid >= close ? color.rgb(255,0,146,0) : color.rgb(0,186,255,0), textcolor=mid >= close ? color.white : color.white, style=mid >= close ? label.style_label_down : label.style_label_up))

        array.set(sr_lines, x + 1, line.new(x1=bar_index, y1=mid, x2=bar_index - 1, y2=mid, extend=extend.both, color=mid >= close ? resistancecolor : supportcolor, style=Lstyle, width=linewidth))

f_crossed_over() =>
    ret = false
    for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
        if close[1] <= mid and close > mid
            ret := true
            ret
    ret

f_crossed_under() =>
    ret = false
    for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
        float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
        if close[1] >= mid and close < mid
            ret := true
            ret
    ret

alertcondition(f_crossed_over(), title='Resistance Broken', message='Resistance Broken')
alertcondition(f_crossed_under(), title='Support Broken', message='Support Broken')



showDashboard = input.bool(true, title='Enable dashboard', inline='dashboard')
dashboardType = ('Advanced dashboard')

xDashBoard = input.int(80, 'dashboard distance', minval=20, maxval=1000, step=10)



// Security function
secSMA(_res) =>
    request.security(syminfo.tickerid, showDashboard ? _res : timeframe.period, ta.sma(ohlc4, 200) < close, lookahead=barmerge.lookahead_on)



//}


advDash = dashboardType == 'Advanced dashboard'


// Simple dashboard has the following timeframes in it
    // 1. Current
trendCurrent = ta.sma(close, 200) < close ? 'Bullish??' : 'Bearish??'


    // 2. 15min
trend15min = secSMA(showDashboard ? '15' : '15') ? 'Bullish??' : 'Bearish??'

    // 3. 1hr
trend1hr = secSMA(showDashboard ? '60' : '15') ? 'Bullish??' : 'Bearish??'

    // 4. 4hr
trend4hr = secSMA(showDashboard ? '240' : '15') ? 'Bullish??' : 'Bearish??'

    // 5. 1D
trend1d = secSMA(showDashboard ? '1D' : '15') ? 'Bullish??' : 'Bearish??'



// Advanced dashboard trends
    // 1. 1min
trend1min = secSMA(advDash and showDashboard ? '1' : '15') ? 'Bullish??' : 'Bearish??'

    // 2. 3min
trend3min = secSMA(advDash and showDashboard ? '3' : '15') ? 'Bullish??' : 'Bearish??'

    // 3. 5min
trend5min = secSMA(advDash and showDashboard ? '5' : '15') ? 'Bullish??' : 'Bearish??'

    // 4. 10min
trend10min = secSMA(advDash and showDashboard ? '10' : '15') ? 'Bullish??' : 'Bearish??'

    // 5. 30min
trend30min = secSMA(advDash and showDashboard ? '30' : '15') ? 'Bullish??' : 'Bearish??'

    // 6. 2hr
trend12hr = secSMA(advDash and showDashboard ? '720' : '15') ? 'Bullish??' : 'Bearish??'

    // 7. 12hr
trend2hr = secSMA(advDash and showDashboard ? '120' : '15') ? 'Bullish??' : 'Bearish??'






rsiTrend = ta.rsi(close, 14)

// RSI condition
rsiCond = rsiTrend < 30 ? 'Oversold (' + str.tostring(math.round(rsiTrend, 2)) + ')' : rsiTrend > 70 ? 'Overbought (' + str.tostring(math.round(rsiTrend, 2)) + ')' : 'Healthy (' + str.tostring(math.round(rsiTrend, 2)) + ')'


// ATR function
atrTrend = ta.atr(14)
atrTrendCond = atrTrend > ta.ema(ta.sma(atrTrend, 100), 100) ? 'Trending' : 'Ranging'


btime = int(ta.sma(time - time[1], 50))

label dashboard = na

if showDashboard
    dashboard := label.new(x=time + btime * xDashBoard, y=(ta.highest(20) + ta.lowest(20)) / 2, text='??discord.gg/indicator??' + '\n\nCurrent Trend: ' +  trendCurrent + '\nPrice condition: ' + rsiCond + '\nVolume: ' + str.tostring(math.round(volume * close, 2)) + ' ' + syminfo.currency + '\nVolatility: ' + atrTrendCond + '\n\n_____________________'  + (advDash ? '\n\n1min: ' + trend1min : '') + (advDash ? '\n3min: ' + trend3min : '') + (advDash ? '\n5min: ' + trend5min : '') + (advDash ? '\n10min: ' + trend10min : '') + '\n15min: ' + trend15min + (advDash ? '\n30min: ' + trend30min : '') + '\n1hr: ' + trend1hr + (advDash ? '\n2hr: ' + trend2hr : '') + '\n4hr: ' + trend4hr + (advDash ? '\n12hr: ' + trend12hr : '') + '\nDaily: ' + trend1d, color=color.black, textcolor=color.white, style=label.style_label_left, xloc=xloc.bar_time, yloc=yloc.price, textalign=text.align_left)
    dashboard

label.delete(dashboard[1])

